<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .point {
      color: red
    }
  </style>
</head>
<body>
<pre style="font-size: 18px">
  JavaScript没有class类(因为弱类型，动态的)ES6->class语法糖
  每个实例对象（ object ）都有一个私有属性（获取的操纵方式不同）（称之为 __proto__ ）指向它的<span class="point">构造函数->原型对象(prototype)</span>
  null是原型链的最后一个环节
  几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
  对象属性也可以包含函数
  函数的prototype是null
  在 JavaScript 中，构造器其实就是一个普通的函数。当使用 new 操作符 来作用这个函数时，它就可以被称为构造方法（构造函数）。
  只有被new的函数称为构造函数
  遍历对象的属性时，原型链上的每个可枚举属性都会被枚举出来。（可以指定不遍历的属性）
  Object.keys()
  Object.getOwnPropertyNames(o)
  不应该去扩展原型
  模拟出的 “类”，也只是一个函数对象
 <pre class="point">
  function A 有一个叫做 prototype 的特殊属性。该特殊属性可与 JavaScript 的 new 操作符一起使用。所有的都是实例（对象）。即使我们模拟出的 “类”，也只是一个函数对象。
  function m2() {

  }
  function m3() {
    this.a = 3
  }

  let m22=new m2()
  console.log(m2.prototype)//用在方法上
  console.log(Object.getPrototypeOf(m22))//用在实例上
  prototype 是用于类/方法的，而 Object.getPrototypeOf() 是用于实例的（instances），两者功能一致。都是获取原型
 </pre>
  因此，当你执行：
  var o = new Foo();
  JavaScript 实际上执行的是：
  var o = new Object();
  o.__proto__ = Foo.prototype;
  Foo.call(o);

  o.someProp;
  它检查 o 是否具有 someProp 属性。
  如果没有，它会查找 Object.getPrototypeOf(o).someProp，
  如果仍旧没有，它会继续查找 Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp直到找到null的时候
</pre>
<script>

  console.log('prototype')
  let obj1 = {
    a: 10
  }
  console.group('start')
  console.log(obj1.a)
  console.log(Object.keys(obj1))
  // console.log(obj1.__proto__)//chrome提供
  console.log(Object.getPrototypeOf(obj1))//es5
  console.log(Object.getPrototypeOf(Object.getPrototypeOf(obj1)))
  console.groupEnd()
  console.group('start')
  let o = {
    a: 2,
    m: function () {
      return this.a + 1
    }
  }
  console.log(o.m()) // 3
  let p = Object.create(o)//继承
  p.a = 4 // 创建 p 的自身属性 'a'
  console.log(p.m()) // 5
  console.log(Object.getPrototypeOf(p))
  console.log(Object.getPrototypeOf(Object.getPrototypeOf(p)))
  console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(p))))
  console.groupEnd()
  console.group('start')

  function doSomething1() {
  }//这个是构造函数
  console.log(doSomething1.prototype)
  // 和声明函数的方式无关，
  // JavaScript 中的函数永远有一个默认原型属性。
  let doSomething2 = function () {
  }
  console.log(doSomething2.prototype)
  console.groupEnd()
  console.group('start')

  function doSomething3() {
  }//这个是构造函数
  console.log(doSomething3.prototype)
  doSomething3.prototype.name = 'hg'
  console.log(doSomething3.prototype)
  let people = new doSomething3()
  people.age = 10
  console.log(Object.getPrototypeOf(people))
  console.log(people)
  console.log(people.__proto__ === doSomething3.prototype)
  console.groupEnd()
  console.group('使用语法结构创建的对象')

  let obj2 = {a: 1}
  console.log(Object.getPrototypeOf(obj2))
  console.log(obj2.hasOwnProperty('xx'))

  let arrays = ["yo", "whadup", "?"]
  console.log(Object.getPrototypeOf(arrays))

  function m1() {
    return 2
  }

  console.log(Object.getPrototypeOf(m1))
  console.groupEnd()
  console.group('使用构造器创建的对象')

  function Graph() {
    this.vertices = []
    this.edges = []
  }

  Graph.prototype = {
    addVertex: function (v) {
      this.vertices.push(v)
    }
  }
  let g = new Graph()
  console.log(g)
  console.groupEnd()
  console.group('使用 Object.create 创建的对象--可以构造原型链')
  let aa = {a: 1}
  let bb = Object.create(aa)
  bb.bb = 2
  console.log(bb)
  let cc = Object.create(bb)
  console.log(cc)
  console.log(cc.hasOwnProperty('cc'))
  console.groupEnd()
  console.group('使用class关键字创建的对象语法糖--可以构造原型链')

  class Polygon {
    constructor(height, width) {
      this.height = height
      this.width = width
    }
  }

  class Square extends Polygon {
    constructor(sideLength) {
      super(sideLength, sideLength)
    }

    get area() {
      return this.height * this.width
    }

    set sideLength(newLength) {
      this.height = newLength
      this.width = newLength
    }
  }

  let square = new Square(2)

  console.log(square)
  console.groupEnd()
  console.group('start')
  let dd = {dd: 1}
  console.log(dd.hasOwnProperty('dd'))
  console.log(Object.keys(dd))//获取当前的所有属性/不会去原型链查找
  console.groupEnd()
  console.group('function A 有一个叫做 prototype,该特殊属性可与 JavaScript 的 new 操作符一起使用。')
  function m2() {

  }
  function m3() {
    this.a = 3
  }

  let m22=new m2()
  console.log(m2.prototype)//用在类上
  console.log(Object.getPrototypeOf(m22))//用在实例上
  console.log(m22)
  console.log(m3.prototype)
  console.groupEnd()
  console.groupEnd()
</script>
</body>
</html>
